﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExplorerService.Common;

namespace ExplorerService.Managers
{
    public sealed class ClientSessionManager
    {
        private static ClientSessionManager _instance;
        private static readonly object Padlock = new object();
        ClientSessionManager() { }

        /// <summary>
        /// Gets the instance of the session manager
        /// </summary>
        public static ClientSessionManager Instance
        {
            get
            {
                lock (Padlock)
                {
                    return _instance ?? (_instance = new ClientSessionManager());
                }
            }
        }

        /// <summary>
        /// Stores the client sessions
        /// </summary>
        private readonly List<ClientSession> _sessions = new List<ClientSession>();


        /// <summary>
        /// Gets the client session for the specified sessionId
        /// </summary>
        /// <param name="sessionId"></param>
        /// <returns></returns>
        public ClientSession this[Guid sessionId]
        {
            get
            {
                return _sessions.FirstOrDefault(session => session.SessionId == sessionId);
            }

        }


        /// <summary>
        /// Creates a new client session and returns the session ID
        /// </summary>
        /// <returns></returns>
        public Guid StartNewClientSession()
        {
            var session = new ClientSession { SessionId = Guid.NewGuid() };
            _sessions.Add(session);
            BroadcastSessionStart(session.SessionId);
            return session.SessionId;
        }


        /// <summary>
        /// Validates the session Id
        /// </summary>
        public bool ValidSessionId(Guid sessionId)
        {
            return this[sessionId] != null;
        }


        /// <summary>
        /// Removes the client session which has the specified Id
        /// </summary>
        /// <param name="sessionId"></param>
        public void EndSession(Guid sessionId)
        {
            var session = this[sessionId];
            if (session == null) return;
            _sessions.Remove(session);
            BroadcastSessionEnd(sessionId);
            session.TerminateServices();
        }

        /// <summary>
        /// Triggers the SessionEnded event
        /// </summary>
        private void BroadcastSessionEnd(Guid sessionId)
        {
            if (SessionEnded == null) return;
            SessionEnded(sessionId);
        }


        /// <summary>
        /// Triggers the SessionStarted event
        /// </summary>
        private void BroadcastSessionStart(Guid sessionId)
        {
            if (SessionStarted == null) return;
            SessionStarted(sessionId);
        }


        /// <summary>
        /// Event triggered when a session has started. Not thread safe.
        /// </summary>
        public event SessionStartedHandler SessionStarted;
        public delegate void SessionStartedHandler(Guid sessionId);


        /// <summary>
        /// Event triggered when a session has ended. Not thread safe.
        /// </summary>
        public event SessionEndedHandler SessionEnded;
        public delegate void SessionEndedHandler(Guid sessionId);

    }

}
